package labox.innovation.gameserver.model.actor.stat;

import labox.innovation.config.Config;
import labox.innovation.gameserver.model.L2Skill;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.skills.Calculator;
import labox.innovation.gameserver.skills.Env;
import labox.innovation.gameserver.skills.Formulas;
import labox.innovation.gameserver.skills.Stats;
import labox.innovation.util.Rnd;

public class CharStat {

	// =========================================================
	// Data Field
	protected L2Character _activeChar;

	protected int _exp;

	protected int _level = 1;

	public CharStat(L2Character activeChar) {
		_activeChar = activeChar;
	}

	public L2Character getActiveChar() {
		return _activeChar;
	}

	// =========================================================
	// Method - Public
	/**
	 * 使用状态修饰符计算使用在目标角色对象上的新的值。<BR>
	 * <BR>
	 *
	 * <B><U> 概念</U> :</B><BR>
	 * <BR>
	 * 每一个L2Character都拥有一个被称作<B>”Calculator“</B>的计算器表，每一个Calculator
	 * （一个stats就是一个Calculator） 都拥有一个Func 对象表。一个Func对象是一种数学函数，
	 * 他被用来计算stats的修饰符（例如：REGENERATE_HP_RATE...）<BR>
	 * <BR>
	 *
	 * FuncAtkAccuracy -> Math.sqrt(_player.getDEX())*6+_player.getLevel()<BR>
	 * <BR>
	 *
	 *当一个calculator的calc方法被调用的时候，根据<B>_order</B>的优先级每一个数学方法被调用，事实上，拥
	 *有最低优先级的函数被最快的执行，而有相同指令的函数通过制定的顺序来执行。计算的结果被存储在一个Env类的对象
	 *的value属性上<BR>
	 *<BR>
	 *
	 * @param stat 计算新的值的状态修饰符
	 *          
	 * @param init 在使用状态修饰符之前使用的初始化的值
	 *            
	 * @param target 属性被使用来计算的L2Charcater(ex : CON, INT...)
	 *           
	 * @param skill 属性被使用来计算的L2Skill(ex : Level...)
	 *
	 */
	public final float calcStat(Stats stat, float init, L2Character target, L2Skill skill) {
		if (_activeChar == null)
			return init;

		int id = stat.ordinal();

		Calculator c = _activeChar.getCalculators()[id];

		// If no Func object found, no modifier is applied
		if (c == null || c.size() == 0)
			return init;

		// Create and init an Env object to pass parameters to the Calculator
		Env env = new Env();
		env.player = _activeChar;
		env.target = target;
		env.skill = skill;
		env.value = init;
		// Launch the calculation
		c.calc(env);
		// avoid some troubles with negative stats (some stats should never be negative)
		if (env.value <= 0 && stat != null) {
			switch (stat) {
			case MAX_HP:
			case MAX_MP:
			case MAGIC_DEFENCE:
			case POWER_DEFENCE:
			case MAGIC_ATTACK:
			case POWER_ATTACK_SPEED:
			case MAGIC_ATTACK_SPEED:
			case STAT_CON:
			case STAT_DEX:
			case STAT_INT:
			case STAT_MEN:
			case STAT_STR:
				env.value = 1;
			}
		}
		return env.value;
	}

	/** 
	 * 获得角色的基础力量
	 * @return
	 */
	public int getBaseSTR() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseSTR;
	}

	/** 
	 * 获得角色的基础敏捷值
	 * @return
	 */
	public int getBaseDEX() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseDEX;
	}

	/** 
	 * 获取角色的基础智力值
	 * @return
	 */
	public int getBaseINT() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseINT;
	}

	/** 
	 * 获得角色的基础精神值
	 * @return
	 */
	public int getBaseMEN() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseMEN;
	}

	/** 
	 * 获得角色的基础体质
	 * @return
	 */
	public int getBaseCON() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseCON;
	}

	/** 
	 * 获得角色的力量
	 * @return
	 */
	public final int getSTR() {
		if (_activeChar == null)
			return 1;
		return Formulas.calcBaseAble(_activeChar, (int) calcStat(Stats.STAT_STR, getBaseSTR(), null, null));
	}

	/** 
	 * 获得角色的敏捷
	 * @return
	 */
	public final int getDEX() {
		if (_activeChar == null)
			return 1;
		return Formulas.calcBaseAble(_activeChar, (int) calcStat(Stats.STAT_DEX, getBaseDEX(), null, null));
	}

	/** 
	 * 获取角色的智力值
	 * @return
	 */
	public int getINT() {
		if (_activeChar == null)
			return 1;
		return Formulas.calcBaseAble(_activeChar, (int) calcStat(Stats.STAT_INT, getBaseINT(), null, null));
	}

	/** 
	 * 获得角色的精神值
	 * @return
	 */
	public final int getMEN() {
		if (_activeChar == null)
			return 1;

		return Formulas.calcBaseAble(_activeChar, (int) calcStat(Stats.STAT_MEN, getBaseMEN(), null, null));
	}

	/** 
	 * 获得角色的体质
	 * @return
	 */
	public final int getCON() {
		if (_activeChar == null)
			return 1;
		return Formulas.calcBaseAble(_activeChar, (int) calcStat(Stats.STAT_CON, getBaseCON(), null, null));
	}

	/**
	 * 获得对角色的物理攻击力rnd(minPAtk,maxPAtk)
	 * @param target
	 * @return
	 */
	public int getPAtk() {
		if (_activeChar == null)
			return 1;
		return Rnd.get(getMinPAtk(), getMaxPAtk());
	}

	/**
	 * 获得最小物理攻击力
	 * 修改 by zjj 10.6.14
	 * 计算攻击的公式有误
	 * @param target
	 * @return
	 */
	public int getMinPAtk() {
		if (_activeChar == null)
			return 1;
		// 计算角色的基础最小物理攻击
		float res = Formulas.calcPAtk(_activeChar, _activeChar.getTemplate().basePAtkMin );
//		System.out.println("角色基础最小物理攻击:" + res );
		//最小物理攻击的加成
		res = calcStat(Stats.MIN_POWER_ATTACK, res, null, null);
//		System.out.println("角色基础最小物理攻击加成:" + res );
		//物理攻击的加成
//		res = calcStat( Stats.POWER_ATTACK_ATTI, res, null, null );
//		System.out.println("最终最小物理攻击加成:" + res );
		
		return (int)res;
		
	}

	/**
	 * 获得最大物理攻击力
	 * @param target
	 * @return
	 */
	public int getMaxPAtk() {
		if (_activeChar == null)
			return 1;
		
		// 计算角色的基础最大物理攻击
		float res = Formulas.calcPAtk(_activeChar, _activeChar.getTemplate().basePAtkMax );
		//最大物理攻击的加成
		res = calcStat(Stats.MAX_POWER_ATTACK, res, null, null);
		
		return (int)res;
		
	}

	/**
	 * 获得角色的魔法伤害 
	 */
	public int getMAtk() {
		if (_activeChar == null)
			return 1;
		int attack = Rnd.get(getMinMAtk(), getMaxMAtk());

		// Calculate modifiers Magic Attack
		return (int) calcStat(Stats.MAGIC_ATTACK, attack, null, null);
	}

	/**
	 * 获得最小魔法攻击力
	 * @param target
	 * @param skill
	 * @return
	 */
	public int getMinMAtk() {
		if (_activeChar == null)
			return 1;
		
		// 计算角色的基础最大物理攻击
		float res = Formulas.calcMAtk(_activeChar, _activeChar.getTemplate().baseMAtkMin );
		//最大物理攻击的加成
		res = calcStat(Stats.MIN_MAGIC_ATTACK, res, null, null);
		
		return (int)res;
		
//		float res = calcStat(Stats.MIN_MAGIC_ATTACK, _activeChar.getTemplate().baseMAtkMin, null, null);
//		res = calcStat( Stats.MAGIC_ATTACK_ATTI, res, null, null );
//		
//		return Formulas.calcMAtk(_activeChar, (int) res);
	}

	/**
	 * 获得最大魔法攻击力
	 * @param target
	 * @param skill
	 * @return
	 */
	public int getMaxMAtk() {
		if (_activeChar == null)
			return 1;
		
		// 计算角色的基础最大物理攻击
		float res = Formulas.calcMAtk(_activeChar, _activeChar.getTemplate().baseMAtkMax );
		//最大物理攻击的加成
		res = calcStat(Stats.MAX_MAGIC_ATTACK, res, null, null);
		
		return (int)res;
		
//		float res = calcStat(Stats.MAX_MAGIC_ATTACK, _activeChar.getTemplate().baseMAtkMax, null, null);
//		res = calcStat( Stats.MAGIC_ATTACK_ATTI, res, null, null );
//		// Calculate modifiers Magic Attack
//		return Formulas.calcMAtk(_activeChar, (int) res);
	}

	/** 
	 * 获得角色的物理防御
	 * @param target
	 * @return
	 */
	public int getPDef() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.POWER_DEFENCE, Formulas.calcPDef(_activeChar, _activeChar.getTemplate().basePDef), null, null );
//		return Formulas.calcPDef(_activeChar, (int) calcStat(Stats.POWER_DEFENCE, _activeChar.getTemplate().basePDef, null, null));
	}

	/**
	 * 获得角色的魔法防御值
	 */
	public int getMDef() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.MAGIC_DEFENCE, Formulas.calcMDef(_activeChar, _activeChar.getTemplate().baseMDef), null, null );
//		return Formulas.calcMDef(_activeChar, (int) calcStat(Stats.MAGIC_DEFENCE, _activeChar.getTemplate().baseMDef, null, null));
	}

	/**
	 * 获得角色最大的HP
	 * @return
	 */
	public int getMaxHp() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.MAX_HP, Formulas.calcMaxHp(_activeChar, _activeChar.getTemplate().baseHpMax), null, null );
//		return Formulas.calcMaxHp(_activeChar, (int) calcStat(Stats.MAX_HP, _activeChar.getTemplate().baseHpMax, null, null));
	}

	/**
	 * 获得角色最大的MP
	 * @return
	 */
	public int getMaxMp() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.MAX_MP, Formulas.calcMaxMp(_activeChar, _activeChar.getTemplate().baseMpMax), null, null );
//		return Formulas.calcMaxMp(_activeChar, (int) calcStat(Stats.MAX_MP, _activeChar.getTemplate().baseMpMax, null, null));
	}

	/**
	 * 获得命中率
	 */
	public int getAccuracy() {
		if (_activeChar == null)
			return 0;
		return (int) calcStat(Stats.ACCURACY_COMBAT, _activeChar.getTemplate().baseHitRate, null, null);
	}

	/** 
	 * 获得角色的闪避率
	 * @return
	 */
	public int getEvasionRate() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.EVASION_RATE, _activeChar.getTemplate().baseeVasionRate, null, null);
	}

	/** 
	 * 获得角色的暴击率
	 * @param target
	 * @param skill
	 * @return
	 */
	public int getCriticalHit() {
		if (_activeChar == null)
			return 1;
		int criticalHit = (int) calcStat(Stats.CRITICAL_RATE, _activeChar.getTemplate().baseCritRate, null, null);
		// Set a cap of Critical Hit at 500
		if (criticalHit > Config.MAX_CRIT_RATE)
			criticalHit = Config.MAX_CRIT_RATE;
		return criticalHit;
	}

	/**
	 * 获得物理攻击速度
	 */
	public int getPAtkSpd() {
		if (_activeChar == null)
			return 1;
		return (int) calcStat(Stats.POWER_ATTACK_SPEED, _activeChar.getTemplate().basePAtkSpd, null, null);
	}

	/** 
	 * 获得的角色的物理攻击范围
	 * @return
	 */
	public final int getPhysicalAttackRange() {
		if (_activeChar == null)
			return 1;
		return _activeChar.getTemplate().baseAtkRange;
	}

	/**
	 * 获得角色的移动速度
	 */
	public int getRunSpeed() {
		if (_activeChar == null)
			return 1;
		int baseRunSpd = _activeChar.getTemplate().baseRunSpd;
		if (baseRunSpd == 0)
			return 0;
		return (int) calcStat(Stats.RUN_SPEED, baseRunSpd, null, null);
	}

	/**
	 * 获得角色的流血强化
	 */
	public int getBleed() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.BLEED, _activeChar.getTemplate().baseBleed, null, null);
	}

	/**
	 * 获得角色的中毒强化
	 */
	public int getPosion() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.POISON, _activeChar.getTemplate().basePoison, null, null);
	}

	/**
	 * 获得角色的眩晕强化
	 */
	public int getStun() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.STUN, _activeChar.getTemplate().baseStun, null, null);
	}

	/**
	 * 获得角色的缠绕强化
	 */
	public int getRoot() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.ROOT, _activeChar.getTemplate().baseRoot, null, null);
	}

	/**
	 * 获得角色的定身强化
	 */
	public int getMovement() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.MOVEMENT, _activeChar.getTemplate().baseMovement, null, null);
	}

	/**
	 * 获得角色的混乱强化
	 */
	public int getConfusion() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.CONFUSION, _activeChar.getTemplate().baseConfusion, null, null);
	}

	/**
	 * 获得角色的基础睡眠强化
	 */
	public int getSleep() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.SLEEP, _activeChar.getTemplate().baseSleep, null, null);
	}

	/**
	 * 获得角色的流血抗性
	 */
	public int getBleedVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.BLEED_VULN, _activeChar.getTemplate().baseSleepVuln, null, null);
	}

	/**
	 * 获得角色的基础中毒抗性
	 */
	public int getPoisonVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.POISON_VULN, _activeChar.getTemplate().basePoisonVuln, null, null);
	}

	/**
	 * 获得角色的眩晕抗性
	 */
	public int getStunVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.STUN_VULN, _activeChar.getTemplate().baseStunVuln, null, null);
	}

	/**
	 * 获得角色的缠绕抗性
	 */
	public int getRootVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.ROOT_VULN, _activeChar.getTemplate().baseRootVuln, null, null);
	}

	/**
	 * 获得角色的缠绕抗性
	 */
	public int getMovementVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.MOVEMENT_VULN, _activeChar.getTemplate().baseMovementVuln, null, null);
	}

	/**
	 * 获得角色的混乱抗性
	 */
	public int getConfusionVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.CONFUSION_VULN, _activeChar.getTemplate().baseConfusionVuln, null, null);
	}

	/**
	 * 获得角色的睡眠抗性
	 */
	public int getSleepVuln() {
		if (_activeChar == null)
			return 1;
		return (int)calcStat(Stats.SLEEP_VULN, _activeChar.getTemplate().baseSleepVuln, null, null);
	}

	/**
	 * 获得角色的经验值
	 * @return
	 */
	public int getExp() {
		return _exp;
	}
	

	/**
	 * 设置角色的经验值
	 * @param value
	 */
	public void setExp(int value) {
		_exp = value;
	}

	/**
	 * 获取角色的等级
	 * @return
	 */
	public int getLevel() {
		return _level;
	}

	/**
	 * 设置角色的等级
	 * @param value
	 */
	public void setLevel(int value) {
		_level = value;
	}

	/** 
	 * 获得技能的施法范围
	 * @param skill
	 * @return
	 */
	public final int getMagicalAttackRange(L2Skill skill) {
		if (_activeChar == null)
			return 1;
		if (skill != null)
			return skill.getCastRange();
		return _activeChar.getTemplate().baseAtkRange;
	}

	/** Return the MReuse rate (base+modifier) of the L2Character. */
	public final int getMReuseRate(L2Skill skill) {
		if (_activeChar == null)
			return 1;

		//		return calcStat(Stats.MAGIC_REUSE_RATE, _activeChar.getTemplate().baseMReuseRate, null, skill);
		return 1;
	}
}
